package cn.hznc.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hznc.constant.CommonConstant;
import cn.hznc.domain.entity.ToolPartEntity;
import cn.hznc.domain.entity.UserEntity;
import cn.hznc.dto.GapHourDto;
import cn.hznc.excel.ProductionReadListener;
import cn.hznc.utils.factory.ExcelExportContext;
import cn.hznc.utils.factory.ExcelExportStrategy;
import cn.hznc.vo.*;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 通用工具类
 *
 * @Author Administrator
 * @Date 2023/3/23 16:09
 */
@Slf4j
public class CommonUtil {

    private static final DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.CHINA);

    /**
     * 四舍五入约分
     *
     * @param target target
     * @return
     */
    public static BigDecimal setSecondScale(BigDecimal target) {
        if (target == null) {
            return null;
        }
        return target.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     *
     */
    public static boolean isDateTimeFormat(String date) {
        try {
            defaultDateTimeFormatter.parse(date);
        } catch (DateTimeParseException exception) {
            return false;
        }
        return true;
    }

    public static String appendString(List<String> list) {
        if (CollectionUtil.isEmpty(list)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i < list.size() - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }

    /**
     * list手动分页方法
     *
     * @param list     分页前的集合
     * @param pageNum  页码
     * @param pageSize 页数
     * @param <T>
     * @return 分页后的集合
     */
    public static <T> List<T> pageList(List<T> list, int pageNum, int pageSize) {
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }
        //计算总页数
        int page = list.size() % pageSize == 0 ? list.size() / pageSize : list.size() / pageSize + 1;
        //兼容性分页参数错误
        pageNum = pageNum <= 0 ? 1 : pageNum;
        pageNum = pageNum >= page ? page : pageNum;
        // 开始索引
        int begin = 0;
        // 结束索引
        int end = 0;
        if (pageNum != page) {
            begin = (pageNum - 1) * pageSize;
            end = begin + pageSize;
        } else {
            begin = (pageNum - 1) * pageSize;
            end = list.size();
        }
        return list.subList(begin, end);
    }

    public static Date addTime48h() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        int hour = 48;
        Calendar calendar = Calendar.getInstance();
        String thisTime = sdf.format(calendar.getTime());
        System.out.println("当前时间为：" + thisTime);
        calendar.add(Calendar.HOUR, hour);
        return calendar.getTime();
    }

    /**
     * 获取当前时间和24小时之前日期的map
     *
     * @return
     */
    public static Map<String, String> minusTime24h() {
        Map<String, String> dateMap = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        dateMap.put("Data1", sdf.format(new Date()));
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, -1);
        dateMap.put("Data2", sdf.format(cal.getTime()));
        return dateMap;
    }

    public static List<List<ToolPartEntity>> subList(List<ToolPartEntity> toolPartEntities, Integer size) {
        List<List<ToolPartEntity>> listGroup = new ArrayList<List<ToolPartEntity>>();
        int listSize = toolPartEntities.size();
        //子集合的长度
        int toIndex = size;
        for (int i = 0; i < toolPartEntities.size(); i += size) {
            if (i + size > listSize) {
                toIndex = listSize - i;
            }
            List<ToolPartEntity> newList = toolPartEntities.subList(i, i + toIndex);
            listGroup.add(newList);
        }
        return listGroup;
    }

    public static <T> List<List<T>> subListBySize(List<T> toolPartEntities, Integer size) {
        List<List<T>> listGroup = new ArrayList<List<T>>();
        int listSize = toolPartEntities.size();
        //子集合的长度
        int toIndex = size;
        for (int i = 0; i < toolPartEntities.size(); i += size) {
            if (i + size > listSize) {
                toIndex = listSize - i;
            }
            List<T> newList = toolPartEntities.subList(i, i + toIndex);
            listGroup.add(newList);
        }
        return listGroup;
    }

    public static List<List<String>> subListReload(List<String> toolPartEntities, Integer size) {
        List<List<String>> listGroup = new ArrayList<>();
        int listSize = toolPartEntities.size();
        //子集合的长度
        int toIndex = size;
        for (int i = 0; i < toolPartEntities.size(); i += size) {
            if (i + size > listSize) {
                toIndex = listSize - i;
            }
            List<String> newList = toolPartEntities.subList(i, i + toIndex);
            listGroup.add(newList);
        }
        return listGroup;
    }

    /**
     * 传入两个时间范围，返回这两个时间范围内的所有日期，并保存在一个集合中
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws Exception
     */
    public static List<String> findEveryDay(String beginTime, String endTime) throws ParseException {
        //创建一个放所有日期的集合
        List<String> dates = new ArrayList();

        //创建时间解析对象规定解析格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //将传入的时间解析成Date类型,相当于格式化
        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);

        //将格式化后的第一天添加进集合
        dates.add(sdf.format(dBegin));

        //使用本地的时区和区域获取日历
        Calendar calBegin = Calendar.getInstance();

        //传入起始时间将此日历设置为起始日历
        calBegin.setTime(dBegin);

        //判断结束日期前一天是否在起始日历的日期之后
        while (dEnd.after(calBegin.getTime())) {

            //根据日历的规则:月份中的每一天，为起始日历加一天
            calBegin.add(Calendar.DAY_OF_MONTH, 1);

            //得到的每一天就添加进集合
            dates.add(sdf.format(calBegin.getTime()));
            //如果当前的起始日历超过结束日期后,就结束循环
        }
        return dates;
    }

    /**
     * 传入两个时间范围，返回这两个时间范围内的所有日期，并保存在一个集合中
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws Exception
     */
    public static List<String> findEveryDay(Date beginTime, Date endTime) throws ParseException {
        //创建一个放所有日期的集合
        List<String> dates = new ArrayList();

//        //创建时间解析对象规定解析格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//
//        //将传入的时间解析成Date类型,相当于格式化
//        Date dBegin = sdf.parse(beginTime);
//        Date dEnd = sdf.parse(endTime);

        //将格式化后的第一天添加进集合
        dates.add(sdf.format(beginTime));

        //使用本地的时区和区域获取日历
        Calendar calBegin = Calendar.getInstance();

        //传入起始时间将此日历设置为起始日历
        calBegin.setTime(beginTime);

        //判断结束日期前一天是否在起始日历的日期之后
        while (endTime.after(calBegin.getTime())) {

            //根据日历的规则:月份中的每一天，为起始日历加一天
            calBegin.add(Calendar.DAY_OF_MONTH, 1);

            //得到的每一天就添加进集合
            dates.add(sdf.format(calBegin.getTime()));
            //如果当前的起始日历超过结束日期后,就结束循环
        }
        return dates;
    }

    public static List<String> findEveryDayReload(Date beginTime, Date endTime) throws ParseException {
        //创建一个放所有日期的集合
        List<String> dates = new ArrayList();

//        //创建时间解析对象规定解析格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
//        //将传入的时间解析成Date类型,相当于格式化
//        Date dBegin = sdf.parse(beginTime);
//        Date dEnd = sdf.parse(endTime);

        //将格式化后的第一天添加进集合
        dates.add(sdf.format(beginTime));

        //使用本地的时区和区域获取日历
        Calendar calBegin = Calendar.getInstance();

        //传入起始时间将此日历设置为起始日历
        calBegin.setTime(beginTime);

        //判断结束日期前一天是否在起始日历的日期之后
        while (endTime.after(calBegin.getTime())) {

            //根据日历的规则:月份中的每一天，为起始日历加一天
            calBegin.add(Calendar.DAY_OF_MONTH, 1);

            //得到的每一天就添加进集合
            dates.add(sdf.format(calBegin.getTime()));
            //如果当前的起始日历超过结束日期后,就结束循环
        }
        return dates;
    }


    /**
     * 传入两个时间范围，返回这两个时间范围内的所有日期，并保存在一个集合中
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws Exception
     */
    public static List<String> findEveryDayReload1(String beginTime, String endTime) throws ParseException {
        //创建一个放所有日期的集合
        List<String> dates = new ArrayList();

        //创建时间解析对象规定解析格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //将传入的时间解析成Date类型,相当于格式化
        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);

        //将格式化后的第一天添加进集合
        dates.add(sdf.format(dBegin));

        //使用本地的时区和区域获取日历
        Calendar calBegin = Calendar.getInstance();

        //传入起始时间将此日历设置为起始日历
        calBegin.setTime(dBegin);

        //判断结束日期前一天是否在起始日历的日期之后
        while (dEnd.after(calBegin.getTime())) {

            //根据日历的规则:月份中的每一天，为起始日历加一天
            calBegin.add(Calendar.DAY_OF_MONTH, 1);

            //得到的每一天就添加进集合
            dates.add(sdf.format(calBegin.getTime()));
            //如果当前的起始日历超过结束日期后,就结束循环
        }
        return dates;
    }

    public static List<String> findEveryDayReload(String beginTime, String endTime) throws ParseException {
        //创建一个放所有日期的集合
        List<String> dates = new ArrayList();

        //创建时间解析对象规定解析格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //将传入的时间解析成Date类型,相当于格式化
        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);

        //将格式化后的第一天添加进集合
        dates.add(sdf.format(dBegin));
        dates.add(sdf.format(dBegin));
        dates.add(sdf.format(dBegin));

        //使用本地的时区和区域获取日历
        Calendar calBegin = Calendar.getInstance();

        //传入起始时间将此日历设置为起始日历
        calBegin.setTime(dBegin);

        //判断结束日期前一天是否在起始日历的日期之后
        while (dEnd.after(calBegin.getTime())) {

            //根据日历的规则:月份中的每一天，为起始日历加一天
            calBegin.add(Calendar.DAY_OF_MONTH, 1);

            //得到的每一天就添加进集合
            dates.add(sdf.format(calBegin.getTime()));
            dates.add(sdf.format(calBegin.getTime()));
            //如果当前的起始日历超过结束日期后,就结束循环
        }
        return dates;
    }



    /**
     * 获取当前请求session中的用户名
     *
     * @return
     */
    public static String getUserName() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpSession session = request.getSession();
        UserEntity user = (UserEntity) session.getAttribute("user");
        if (ObjectUtil.isNotNull(user)) {
            return user.getUsername();
        }
        return "";
    }

    public static Integer getUserId() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpSession session = request.getSession();
        //UserEntity user = (UserEntity) session.getAttribute("X-token");
        Object attribute = session.getAttribute("X-token");
        if (ObjectUtil.isNotNull(attribute)) {
            //return user.getId();
            return null;
        }
        return null;
    }

    /**
     * @param url        访问地址
     * @param headerMap  header 参数；可以通过下面工具类将string类型转换成map
     * @param contentMap 需要传输参数参数；对象可以通过json转换成map
     * @return 返回网页返回的数据
     */
    public static String postMap(String url, Map<String, String> headerMap, Map<String, String> contentMap) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        List<NameValuePair> content = new ArrayList<NameValuePair>();
        //将content生成entity
        Iterator iterator = contentMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
            content.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
        }
        CloseableHttpResponse response = null;
        try {
            //循环增加header
            Iterator headerIterator = headerMap.entrySet().iterator();
            while (headerIterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIterator.next();
                post.addHeader(elem.getKey(), elem.getValue());
            }
            if (content.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(content, "UTF-8");
                post.setEntity(entity);
            }
            //发送请求并接收返回数据
            response = httpClient.execute(post);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                //获取response的body部分
                HttpEntity entity = response.getEntity();
                //读取reponse的body部分并转化成字符串
                result = EntityUtils.toString(entity);
            }
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return null;
    }


    /**
     * Header字符串转map
     *
     * @param zz
     * @return
     */
    public static Map<String, String> splid(String zz) {
        String[] stepOne = zz.split("\n");
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < stepOne.length; i++) {
            String[] stepTwo = stepOne[i].split(": ");
            if (map.get(stepTwo[0]) == null) {
                map.put(stepTwo[0], stepTwo[1]);
            } else {
                map.put(stepTwo[0], stepTwo[1] + "," + map.get(stepTwo[0]));
            }
        }
        return map;
    }

    public static Map<String, String> getMonthTimeRange(Integer month) {
        Map<String, String> retMap = new HashMap<>();
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR));
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date start = cal.getTime();
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        Date end = cal.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        retMap.put("startTime", sdf.format(start));
        retMap.put("endTime", sdf.format(end));
        return retMap;
    }

    public static Date transferTime(String timeStr) {
        String[] split = timeStr.split("/");
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, Integer.parseInt(split[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(split[1]));
        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(split[2]));
        return cal.getTime();
    }

    public static List<IncBoxParamVo> filterBoxParamList(List<IncBoxParamVo> inputList) {
        if (CollectionUtil.isNotEmpty(inputList)) {
            return inputList
                    .stream()
                    .filter(incBoxParamVo -> StringUtil.isNotEmpty(incBoxParamVo.getId()))
                    .filter(incBoxParamVo -> ObjectUtil.isNotNull(incBoxParamVo.getKey_value().get("position")))
                    .filter(incBoxParamVo -> StringUtil.isNotEmpty(incBoxParamVo.getName())&&!" ".equals(incBoxParamVo.getName()))
                    .collect(Collectors.toList());
        }
        return inputList;
    }

    public static List<IncBoxParamVo> parseToolParams(String s) {
        String s1 = s.replaceAll("([-\\w]+)=", "\"$1\":");
        String s2 = s1.replaceAll(":\\s*([-+%.:\\w]+)", ":\"$1\"");
        String s3 = s2.replaceAll("(\"id\"|\"name\"):\\s*,", "$1:\" \",");
        List<IncBoxParamVo> incBoxParamVos = JSONArray.parseArray(s3, IncBoxParamVo.class);
        return filterBoxParamList(incBoxParamVos);
    }

    public static String getProgramString(Object o) {
        if (ObjectUtil.isNull(o)) {
            return "";
        }
        List oList = (List) o;
        return ((List) oList.get(0)).get(0).toString();
    }

    public static String getProgramReload(Object o) {
        if (ObjectUtil.isNull(o)) {
            return "";
        }
        List oList = (List) o;
        if(ObjectUtil.isNull(oList.get(0))){
            return "";
        }
        return oList.get(0).toString();
    }

    public static Integer getPartCount(Object o) {
        if (ObjectUtil.isNull(o)) {
            return 0;
        }
        List oList = (List) o;
        return Integer.parseInt(((List) oList.get(0)).get(0).toString());
    }

    public static Integer randomNumber() {
        Random random = new Random();
        return random.nextInt(90000) + 10000;
    }

    public static List<String> iicStrSplit(String iic) {
        List<String> resultList = new ArrayList<>();
        if (StringUtil.isEmpty(iic)) {
            return resultList;
        }
        //1-10位(index=0)
        resultList.add(iic.substring(0, 10));
        //11-12位(index=1)
        resultList.add(iic.substring(10, 12));
        //13位(index=2)
        resultList.add(iic.substring(12, 13));
        //14位(index=3)
        resultList.add(iic.substring(13, 14));
        //15位(index=4)
        resultList.add(iic.substring(14, 15));
        //18-19位(index=5)
        resultList.add(iic.substring(17, 19));
        //16-17位(index=6)
        resultList.add(iic.substring(15, 17));
        return resultList;
    }

    /**
     * 14位匹配14位切割
     *
     * @param ccws
     * @return
     */
    public static List<String> ccws14Split1(String ccws) {
        List<String> resultList = new ArrayList<>();
        if (StringUtil.isEmpty(ccws)) {
            return resultList;
        }
        //1-3位(index=0)
        resultList.add(ccws.substring(0, 3));
        //4-5位(index=1)
        resultList.add(ccws.substring(3, 5));
        //6-10位(index=2)
        resultList.add(ccws.substring(5, 10));
        return resultList;
    }

    /**
     * 14位匹配28位切割
     *
     * @param ccws
     * @return
     */
    public static List<String> ccws14Split2(String ccws) {
        List<String> resultList = new ArrayList<>();
        if (StringUtil.isEmpty(ccws)) {
            return resultList;
        }
        //1-3位(index=0)
        resultList.add(ccws.substring(0, 3));
        //4-5位(index=1)
        resultList.add(ccws.substring(3, 5));
        //6位(根据倍率进行计算index=2)
        if (ccws.charAt(5) == 'F') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 1000) + "");
            return resultList;
        } else if (ccws.charAt(5) == 'G') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 100) + "");
            return resultList;
        } else if (ccws.charAt(5) == 'H') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 10) + "");
            return resultList;
        } else {
            resultList.add((Integer.parseInt(ccws.substring(6, 10))) + "");
            return resultList;
        }
    }

    public static List<String> ccws28Split(String ccws) {
        List<String> resultList = new ArrayList<>();
        if (StringUtil.isEmpty(ccws)) {
            return resultList;
        }
        //1-3位(index=0)
        resultList.add(ccws.substring(0, 3));
        //4-5位(index=1)
        resultList.add(ccws.substring(3, 5));
        //6位(index=2)
        if (ccws.charAt(5) == 'F') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 1000) + "");
        } else if (ccws.charAt(5) == 'G') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 100) + "");
        } else if (ccws.charAt(5) == 'H') {
            resultList.add((Integer.parseInt(ccws.substring(6, 10)) / 10) + "");
        }
        //28位(index=3)
        if (ccws.charAt(19) == 'F') {
            resultList.add((Integer.parseInt(ccws.substring(20, 24)) / 1000) + "");
        } else if (ccws.charAt(19) == 'G') {
            resultList.add((Integer.parseInt(ccws.substring(20, 24)) / 100) + "");
        } else if (ccws.charAt(19) == 'H') {
            resultList.add((Integer.parseInt(ccws.substring(20, 24)) / 10) + "");
        }
        return resultList;
    }

    public static Date getTimeBeforeConfigure(Integer minutesToPreviousHour) {
        Calendar calendar = Calendar.getInstance();
        Date currentTime = calendar.getTime();

        calendar.setTime(currentTime);
//        int minutes = calendar.get(Calendar.MINUTE);
//        int minutesToPreviousHour = minutes % 60;

        calendar.add(Calendar.MINUTE, -minutesToPreviousHour);
        return calendar.getTime();
    }

    public static Date parseDate(String dateStr) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.parse(dateStr);
    }

    public static Date parseDateReload(String dateStr) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.parse(dateStr);
    }




    public static <T> T getRandomElement(List<T> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }

        Random random = new Random();
        int index = random.nextInt(list.size());

        return list.get(index);
    }

    public static String transferDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }


    public static List<DateVo> splitDate(Date startTime, Date endTime, Date splitStartTime, Date splitEndTime) {
        List<DateVo> resultList = new ArrayList<>();

        //工作开始时间
        Calendar workStartCalendar = Calendar.getInstance();
        workStartCalendar.setTime(splitStartTime);
        Integer workStartHour = workStartCalendar.get(Calendar.HOUR_OF_DAY);
        Integer workStartMinute = workStartCalendar.get(Calendar.MINUTE);
        Integer workStartSecond = workStartCalendar.get(Calendar.SECOND);
        workStartCalendar.setTime(startTime);
        workStartCalendar.set(Calendar.HOUR_OF_DAY, workStartHour);
        workStartCalendar.set(Calendar.MINUTE, workStartMinute);
        workStartCalendar.set(Calendar.SECOND, workStartSecond);
        Date actualworkStartTime = workStartCalendar.getTime();
        //工作结束时间
        Calendar workEndCalendar = Calendar.getInstance();
        workEndCalendar.setTime(splitEndTime);
        Integer workEndtHour = workEndCalendar.get(Calendar.HOUR_OF_DAY);
        Integer workEndMinute = workEndCalendar.get(Calendar.MINUTE);
        Integer workEndSecond = workEndCalendar.get(Calendar.SECOND);
        workEndCalendar.setTime(startTime);
        workEndCalendar.set(Calendar.HOUR_OF_DAY, workEndtHour);
        workEndCalendar.set(Calendar.MINUTE, workEndMinute);
        workEndCalendar.set(Calendar.SECOND, workEndSecond);
        Date actualworkEndTime = workEndCalendar.getTime();

        while (actualworkStartTime.getTime() < endTime.getTime()) {
            DateVo dateVo = new DateVo();

            if (actualworkStartTime.getTime() > startTime.getTime()) {
                dateVo.setStartTime(actualworkStartTime);
            } else {
                dateVo.setStartTime(startTime);
            }
            if (actualworkEndTime.getTime() > endTime.getTime()) {
                dateVo.setEndTime(endTime);
            } else {
                dateVo.setEndTime(actualworkEndTime);
            }
            if (endTime.getTime() > startTime.getTime()) {
                resultList.add(dateVo);
            }
            workStartCalendar.add(Calendar.DAY_OF_MONTH, 1);
            actualworkStartTime = workStartCalendar.getTime();
            workEndCalendar.add(Calendar.DAY_OF_MONTH, 1);
            actualworkEndTime = workEndCalendar.getTime();
        }
        return resultList;
    }

    public static Map<String, String> findStartAndEndOfOneDay(String dateStr) {
        Map<String, String> dateMap = new HashMap<>();
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime startDay = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN);
        LocalDateTime endDay = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX);
        dateMap.put("startTime", startDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        dateMap.put("endTime", endDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return dateMap;
    }

    public static List<Date> findDateList(Date startDate, Date endDate) {
        List<Date> dateList = new ArrayList<>();
        dateList.add(startDate);
        Calendar calendar = new GregorianCalendar();
        for (int i = 1; i < 13; i++) {
            calendar.setTime(startDate);
            calendar.add(Calendar.MONTH, i);
            if (calendar.getTime().compareTo(endDate) < 0) {
                dateList.add(calendar.getTime());
            } else {
                break;
            }
        }
//        //获取每个月开始时间和结束时间
//        List<DateVo> dateVos = new ArrayList<>();
//        Calendar ca = Calendar.getInstance();
//        if(CollectionUtil.isNotEmpty(dateList)){
//            dateList.forEach(date -> {
//                DateVo dateVo = new DateVo();
//                dateVo.setStartTime(date);
//                ca.setTime(date);
//                ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
//                dateVo.setEndTime(ca.getTime());
//                dateVos.add(dateVo);
//            });
//        }
        return dateList;
    }

    public static DateStrVo findDateListReload(Date date) {
        //获取每个月开始时间和结束时间
        Calendar ca = Calendar.getInstance();
        DateVo dateVo = new DateVo();
        dateVo.setStartTime(date);
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        dateVo.setEndTime(ca.getTime());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");

        DateStrVo dateStrVo = new DateStrVo();
        Map<String, String> startDateMap = findStartAndEndOfOneDay(sdf.format(dateVo.getStartTime()));
        Map<String, String> endDateMap = findStartAndEndOfOneDay(sdf.format(dateVo.getEndTime()));
        dateStrVo.setStartTime(startDateMap.get("startTime"));
        dateStrVo.setEndTime(endDateMap.get("endTime"));
        return dateStrVo;
    }

    public static List<DateStrVo> splitDateStr(String startDateStr , String endDateStr) {
        List<DateStrVo> resultList = new ArrayList<>();

        return resultList;
    }

    public static String getToken() {
        Map<String , Object> paramMap = new HashMap<>();
        paramMap.put("usercode" , "admin");
        String post = HttpUtil.post(CommonConstant.USAGE_ADRESS+ "/ZeusoftWebService.svc/api/GetToken", JSONObject.toJSONString(paramMap));
        JSONObject jsonObject = JSONObject.parseObject(post);
        return jsonObject.get("token").toString();
    }

    public static List<Map<String, Object>> getData(String url) {
        Map<String , Object> paramMap = new HashMap<>();
        String token = CommonUtil.getToken();
        paramMap.put("token",token);
        String post = HttpUtil.post(url, JSONObject.toJSONString(paramMap));
        JSONObject jsonObject = JSONObject.parseObject(post);
        Object o = jsonObject.get("data");
        List<Map<String, Object>> data = (List<Map<String, Object>>)o;
        return data;
    }

    public static List<CategoryVo> getDataReload(String url) {
        Map<String , Object> paramMap = new HashMap<>();
        String token = CommonUtil.getToken();
        paramMap.put("token",token);
        String post = HttpUtil.post(url, JSONObject.toJSONString(paramMap));
        JSONObject jsonObject = JSONObject.parseObject(post);
        Object o = jsonObject.get("data");
        List<CategoryVo> data = JSONArray.parseArray(JSONArray.toJSONString(o) , CategoryVo.class);
        return data;
    }

    public static Date getDate(Integer year , Integer month , Integer date , Integer hourOfDay , Integer minute , Integer second) {
        Calendar cal = Calendar.getInstance();
        cal.set(2023,10,24 , 13,59,22);
        return cal.getTime();
    }

    public static Double getDouble(String  timeUsageStr) {
        if(StringUtils.isBlank(timeUsageStr)){
            return 0.0;
        }
        return Double.valueOf(timeUsageStr.substring(0 , timeUsageStr.length()-1));
    }


//    public static MultipartFile fileToMultipartFile(File file) {
//        FileItem fileItem = creatFileItem(file);
//        MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
//        return multipartFile;
//    }
//
//    public static FileItem creatFileItem(File file) {
//
//        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(16, null);
//        FileItem fileItem = diskFileItemFactory.createItem("textField", "image/jpg", true, file.getName());
//
//        int bytesRead = 0;
//        byte[] buffer = new byte[8192];
//
//        try {
//            FileInputStream fileInputStream = new FileInputStream(file);
//            OutputStream outputStream = fileItem.getOutputStream();
//            while ((bytesRead = fileInputStream.read(buffer, 0, 8192)) != -1) {
//                outputStream.write(buffer, 0, bytesRead);
//            }
//            Files.copy(file.toPath(), outputStream);
//            outputStream.close();
//            fileInputStream.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return fileItem;
//    }

    public static MultipartFile getMultipartFile(File file) {
        FileItem item = new DiskFileItemFactory().createItem("file"
                , MediaType.MULTIPART_FORM_DATA_VALUE
                , true
                , file.getName());
        try (InputStream input = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            // 流转移
            IOUtils.copy(input, os);
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid file: " + e, e);
        }

        return new CommonsMultipartFile(item);
    }

    /**
     * 计算一组数据标准差
     * @param data
     * @return
     */
    public static Double calculateStandardDeviation(List<Double> data) {
        if(CollectionUtil.isEmpty(data)){
            return 0.0;
        }
        if(data.size() == 1){
            return data.get(0);
        }
        double sum = 0.0;
        double mean;
        double sumOfSquares =0.0;
        for (Double datum : data) {
            sum += datum;
        }
        mean = sum / data.size();
        for (Double datum : data) {
            sumOfSquares += Math.pow(datum - mean , 2);
        }

        return Math.sqrt(sumOfSquares / data.size());
    }

    /**
     * 计算一组数据平均值差
     * @param data
     * @return
     */
    public static Double calculateAvgValue(List<Double> data) {
        if(CollectionUtil.isEmpty(data)){
            return 0.0;
        }
        double sum = 0.0;
        double mean;
        double sumOfSquares =0.0;
        for (Double datum : data) {
            sum += datum;
        }
        return sum / data.size();
    }

    /**
     * 计算一组数据的正态分布中单个数的概率
     * @return
     */
    public static Double calculateRate(Double mean , Double standardDeviation , Double x) {
        NormalDistribution normalDistribution = new NormalDistribution(mean , standardDeviation);
        double pdf = normalDistribution.density(x);
        return 1 - normalDistribution.cumulativeProbability(x);
    }


    /**
     * 复杂excel表头导出工具方法
     * @return
     */
    public static <T> void exportExcelFile(T t , String templatePath , HttpServletResponse response , String outputFileName) {
        //获取模板
        ClassPathResource classPathResource = new ClassPathResource(templatePath);
        //输入流
        InputStream inputStream = null;

        //输出流
        ServletOutputStream outputStream = null;

        //Excel对象
        ExcelWriter excelWriter = null;
        try{
            //输入流
            inputStream = classPathResource.getInputStream();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(outputFileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            outputStream = response.getOutputStream();

            // InputStream templateStream = getClass().getClassLoader().getResourceAsStream(CommonConstant.Tool_DEMAND_TEMPLATE_PATH);
            excelWriter = EasyExcel.write(response.getOutputStream())
                    .autoCloseStream(Boolean.TRUE)
                    .withTemplate(inputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            // 列表

//            if(t instanceof ToolUsageReportExport){
//                ExcelExportContext excelExportContext = new ExcelExportContext((ToolUsageReportExport)t);
//                excelExportContext.buildExcelWriter(excelWriter , fillConfig , writeSheet);
//            }else if(t instanceof OrderForecastReportExport){
//                ExcelExportContext excelExportContext = new ExcelExportContext((OrderForecastReportExport)t);
//                excelExportContext.buildExcelWriter(excelWriter , fillConfig , writeSheet);
//            }
            ExcelExportContext excelExportContext = new ExcelExportContext();
            excelExportContext.buildExcelWriterByStrategy(t , excelWriter , fillConfig , writeSheet);

            // 结束写入
            excelWriter.finish();

        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            log.error("export order detail failed=====>", e);
        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
            //关闭流
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static List<List<LinkedHashMap>> uploadZipFile(MultipartFile file) {
        List<List<LinkedHashMap>> resultList = new ArrayList<>();
        List<String> batchadd = FileUtils.batchadd(file);
        if (CollectionUtil.isNotEmpty(batchadd)) {
            batchadd.forEach(s -> {
                ProductionReadListener easyExcelListener = new ProductionReadListener();
                ExcelReader excelReader = null;
                try {
                    excelReader = EasyExcelFactory.read(new FileInputStream(s), easyExcelListener).build();
                    List<ReadSheet> sheets = excelReader.excelExecutor().sheetList();
                    Map<Integer, List<LinkedHashMap>> sheetInfos = new HashMap<>(sheets.size());
                    for (ReadSheet sheet : sheets) {
                        Integer sheetNo = sheet.getSheetNo();
                        excelReader.read(sheet);
                        sheetInfos.put(sheetNo, easyExcelListener.getListMap());
                    }
                    //最终数据
                    List<LinkedHashMap> mapList = sheetInfos.get(0);
                    resultList.add(mapList);
                } catch (IOException e) {
                    log.error("10001", "解析失败");
                }
            });
        }
        return resultList;
    }

    /**
     * 将原list按1000条分为一组list
     * @param originalList
     * @return
     */
    public static <T> List<List<T>> groupList(List<T> originalList) {
        int listSize = originalList.size();
        int groupCount = (int) Math.ceil((double) listSize / 1000);
        List<List<T>> groupedLists = new ArrayList<>();
        for (int i = 0; i < groupCount; i++) {
            groupedLists.add(new ArrayList<>());
        }
        for (int i = 0; i < listSize; i++) {
            int groupIndex = i/1000;
            groupedLists.get(groupIndex).add(originalList.get(i));
        }
        return groupedLists;
    }

    /**
     * 将原list按500条分为一组list
     * @param originalList
     * @return
     */
    public static <T> List<List<T>> groupListReload(List<T> originalList) {
        int listSize = originalList.size();
        int groupCount = (int) Math.ceil((double) listSize / 500);
        List<List<T>> groupedLists = new ArrayList<>();
        for (int i = 0; i < groupCount; i++) {
            groupedLists.add(new ArrayList<>());
        }
        for (int i = 0; i < listSize; i++) {
            int groupIndex = i/500;
            groupedLists.get(groupIndex).add(originalList.get(i));
        }
        return groupedLists;
    }

    /**
     * 获取当天24小时间隔时间
     * @return
     */
    public static List<GapHourDto> getDayHourlyGap() {
        List<GapHourDto> dateTimeList = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        //calendar.set(2024,Calendar.FEBRUARY , 27 ,0 , 0 ,0);test
        for (int i = 1; i < 23; i++) {
            GapHourDto gapHourDto = new GapHourDto();
            gapHourDto.setStart(calendar.getTime());
            calendar.add(Calendar.HOUR_OF_DAY , 1);
            gapHourDto.setEnd(calendar.getTime());
            dateTimeList.add(gapHourDto);
        }
        return dateTimeList;
    }


    /**
     * 获取当前时间和今日零点的时间间隔
     * @return
     */
    public static Map<String , Date> getTimeDifferenceToZero(){
        Date nowDate = new Date(); // 当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate);
        calendar.set(Calendar.HOUR_OF_DAY, 24);// 设置一天中的第几个小时
        calendar.set(Calendar.MINUTE, 0); // 第几分钟
        calendar.set(Calendar.SECOND, 0); // 第几秒
        Date zero = calendar.getTime(); // 零点
        Map<String , Date> dateMap = new HashMap<>();
        dateMap.put("zeroTime" , zero);
        dateMap.put("nowTime" , nowDate);
        //Long differ = zero.getTime() - nowDate.getTime();
        return dateMap;
    }


}
